#!/usr/bin/env bash

# ========================================
# WonderTrader 测试执行脚本 (增强版)
# 功能：运行测试用例并提供详细的结果分析和日志记录
# 参考：build_release.sh
# ========================================

# 脚本开始时间
START_TIME=$(date +%s)
TEST_TIMESTAMP=$(date +%Y%m%d_%H%M%S)

# 检测CPU核心数
CPU_CORES=$(nproc)
# 使用70%的CPU核心数进行编译，并四舍五入到最接近的整数
COMPILE_JOBS=$(echo "$CPU_CORES * 0.7" | bc | xargs printf "%.0f")
# 确保至少使用1个线程
if [ $COMPILE_JOBS -lt 1 ]; then
    COMPILE_JOBS=1
fi

# ========================================
# 日志配置
# ========================================

# 确保测试目录存在
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BUILD_DIR="$SCRIPT_DIR/build_test"

# 创建日志目录
LOG_DIR="$SCRIPT_DIR/logs"
mkdir -p "$LOG_DIR"

# 日志文件路径（使用绝对路径）
TEST_LOG="$LOG_DIR/test_run_${TEST_TIMESTAMP}.log"
RESULTS_LOG="$LOG_DIR/test_results_${TEST_TIMESTAMP}.log"
FAILURES_LOG="$LOG_DIR/test_failures_${TEST_TIMESTAMP}.log"
SUMMARY_LOG="$LOG_DIR/test_summary_${TEST_TIMESTAMP}.log"
LATEST_LOG="$LOG_DIR/latest_test.log"

# 清理旧的latest_test.log链接
rm -f "$LATEST_LOG"

# 日志函数
log_info() {
    local message="[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] $1"
    echo "$message" | tee -a "$TEST_LOG"
}

# 显示带颜色的进度信息
log_progress() {
    local message="[$(date '+%Y-%m-%d %H:%M:%S')] [PROGRESS] $1"
    echo -e "\033[36m$message\033[0m" | tee -a "$TEST_LOG"
}

log_warning() {
    local message="[$(date '+%Y-%m-%d %H:%M:%S')] [WARNING] $1"
    echo -e "\033[33m$message\033[0m" | tee -a "$TEST_LOG" "$FAILURES_LOG"
}

log_error() {
    local message="[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] $1"
    echo -e "\033[31m$message\033[0m" | tee -a "$TEST_LOG" "$FAILURES_LOG"
}

log_success() {
    local message="[$(date '+%Y-%m-%d %H:%M:%S')] [SUCCESS] $1"
    echo -e "\033[32m$message\033[0m" | tee -a "$TEST_LOG"
}

log_header() {
    local message="$1"
    echo "========================================" | tee -a "$TEST_LOG"
    echo "$message" | tee -a "$TEST_LOG"
    echo "========================================" | tee -a "$TEST_LOG"
}

# ========================================
# 测试信息记录
# ========================================

# 记录测试开始信息
log_header "WonderTrader 测试套件执行开始"
log_info "测试时间戳: $TEST_TIMESTAMP"
log_info "检测到 $CPU_CORES 个CPU核心，将使用 $COMPILE_JOBS 个线程进行编译"
log_info "测试日志: $TEST_LOG"
log_info "结果日志: $RESULTS_LOG"
log_info "失败日志: $FAILURES_LOG"
log_info "测试摘要: $SUMMARY_LOG"

# 记录系统信息
{
    echo "========================================"
    echo "系统环境信息"
    echo "========================================"
    echo "测试时间: $(date)"
    echo "主机名: $(hostname)"
    echo "操作系统: $(uname -a)"
    echo "CPU信息: $(lscpu | grep 'Model name' | cut -d: -f2 | xargs)"
    echo "内存信息: $(free -h | grep '^Mem:' | awk '{print $2 " 总内存, " $3 " 已使用, " $7 " 可用"}')"
    echo "磁盘空间: $(df -h . | tail -1 | awk '{print $4 " 可用空间"}')"
    echo "CMake版本: $(cmake --version | head -1)"
    echo "GCC版本: $(gcc --version | head -1)"
    echo "Make版本: $(make --version | head -1)"
    echo "========================================"
} >> "$TEST_LOG"

# 设置环境变量，避免anaconda3干扰
export PATH="/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin"
log_info "已设置环境变量PATH: $PATH"

# ========================================
# 依赖检查
# ========================================

check_dependencies() {
    log_header "依赖检查阶段"
    log_info "开始检查依赖工具..."

    local missing_deps=()

    if ! command -v cmake &> /dev/null; then
        missing_deps+=("cmake")
    fi

    if ! command -v make &> /dev/null; then
        missing_deps+=("make")
    fi

    if ! command -v pkg-config &> /dev/null; then
        missing_deps+=("pkg-config")
    fi

    # 检查Google Test
    if ! pkg-config --exists gtest 2>/dev/null && ! find /usr -name "libgtest*" 2>/dev/null | head -1 | grep -q .; then
        missing_deps+=("googletest")
    fi

    if [ ${#missing_deps[@]} -gt 0 ]; then
        log_error "缺少依赖: ${missing_deps[*]}"
        log_error "请安装缺少的依赖后重新运行"
        exit 1
    fi

    log_success "依赖检查完成"
}

# ========================================
# 创建构建目录
# ========================================

setup_build_directory() {
    log_header "构建目录设置"
    
    if [ -d "$BUILD_DIR" ]; then
        log_info "清理现有构建目录..."
        rm -rf "$BUILD_DIR"
    fi

    log_info "创建构建目录..."
    mkdir -p "$BUILD_DIR"
    cd "$BUILD_DIR"
    
    log_success "构建目录设置完成"
}

# ========================================
# CMake配置阶段
# ========================================

configure_tests() {
    log_header "CMake 配置阶段"
    log_info "开始CMake配置..."

    # 执行CMake配置并记录输出
    {
        echo "CMake配置开始时间: $(date)"
        echo "CMake命令: cmake .."
        echo "----------------------------------------"
    } >> "$TEST_LOG"

    cmake .. 2>&1 | tee -a "$TEST_LOG"
    CMAKE_EXIT_CODE=${PIPESTATUS[0]}
    
    if [ $CMAKE_EXIT_CODE -eq 0 ]; then
        log_success "CMake配置成功"
    else
        log_error "CMake配置失败（退出码: $CMAKE_EXIT_CODE）"
        exit 1
    fi
}

# ========================================
# 编译测试阶段
# ========================================

build_tests() {
    log_header "测试编译阶段"
    log_info "开始并行编译测试（使用 $COMPILE_JOBS 个线程）..."
    log_progress "编译输出将同时显示在终端和日志文件中..."

    # 记录编译开始时间
    COMPILE_START_TIME=$(date +%s)

    {
        echo "编译开始时间: $(date)"
        echo "编译命令: make -j$COMPILE_JOBS"
        echo "线程数: $COMPILE_JOBS"
        echo "----------------------------------------"
    } >> "$TEST_LOG"

    # 执行编译并同时记录输出
    echo "" | tee -a "$TEST_LOG"  # 添加空行以便更好的可读性
    make -j$COMPILE_JOBS 2>&1 | tee -a "$TEST_LOG" | tee /tmp/test_build_output_$$.tmp
    MAKE_EXIT_CODE=${PIPESTATUS[0]}
    echo "" | tee -a "$TEST_LOG"  # 添加空行

    # 分析编译输出中的警告和错误
    if [ -f /tmp/test_build_output_$$.tmp ]; then
        # 改进的警告检测：匹配实际的警告消息
        grep -i "warning:" /tmp/test_build_output_$$.tmp >> "$FAILURES_LOG" 2>/dev/null || true
        
        # 改进的错误检测：匹配实际的错误消息，排除文件名中的error
        grep -E "(^[^:]*:[^:]*:\s*error:|^Error\s|^\*\*\*\s*Error|\berror\s*:|make.*Error)" /tmp/test_build_output_$$.tmp | grep -v -E "(Building|Linking).*error_.*\.(c|cpp|o|so|a)(\s|$)" >> "$FAILURES_LOG" 2>/dev/null || true
        
        rm -f /tmp/test_build_output_$$.tmp
    fi

    COMPILE_END_TIME=$(date +%s)
    COMPILE_TIME=$((COMPILE_END_TIME - COMPILE_START_TIME))

    if [ $MAKE_EXIT_CODE -eq 0 ]; then
        log_success "测试编译成功完成"
        log_info "编译耗时: ${COMPILE_TIME} 秒"
    else
        log_error "测试编译失败"
        echo "详细错误信息请查看: $FAILURES_LOG" | tee -a "$TEST_LOG"
        exit 1
    fi
}

# ========================================
# 测试超时监控函数
# ========================================

execute_tests_with_timeout() {
    log_info "启动测试执行（每个测试用例3秒强制超时）"
    
    # 获取所有测试用例列表
    local test_list_file="/tmp/test_list_$$.txt"
    ./wondertrader_tests --gtest_list_tests > "$test_list_file"
    
    # 解析测试用例
    local current_suite=""
    local test_cases=()
    
    while IFS= read -r line; do
        if [[ "$line" =~ ^[A-Za-z] ]] && [[ ! "$line" =~ ^[[:space:]] ]]; then
            # 测试套件行
            current_suite=$(echo "$line" | sed 's/\.$//')
        elif [[ "$line" =~ ^[[:space:]]+[A-Za-z] ]]; then
            # 测试用例行
            local test_case=$(echo "$line" | sed 's/^[[:space:]]*//')
            test_cases+=("${current_suite}.${test_case}")
        fi
    done < "$test_list_file"
    
    log_info "找到 ${#test_cases[@]} 个测试用例，开始逐个执行..."
    
    local total_tests=${#test_cases[@]}
    local passed_tests=0
    local failed_tests=0
    local timeout_tests=0
    local current_test_num=0
    
    # 记录测试开始
    {
        echo "=========================================="
        echo "开始逐个执行测试用例（每个3秒超时）"
        echo "总测试数: $total_tests"
        echo "执行时间: $(date)"
        echo "=========================================="
    } | tee -a "$TEST_LOG"
    
    # 逐个执行测试用例
    for test_case in "${test_cases[@]}"; do
        current_test_num=$((current_test_num + 1))
        
        echo "" | tee -a "$TEST_LOG"
        echo "[${current_test_num}/${total_tests}] 执行测试: $test_case" | tee -a "$TEST_LOG"
        
        # 使用timeout执行单个测试
        local test_start_time=$(date +%s)
        
        if timeout 3 ./wondertrader_tests --gtest_filter="$test_case" --gtest_color=yes --gtest_print_time=1 > /tmp/single_test_$$.tmp 2>&1; then
            local test_end_time=$(date +%s)
            local test_duration=$((test_end_time - test_start_time))
            local test_duration_ms=$((test_duration * 1000))
            
            # 检查测试结果
            if grep -q "\[.*FAILED.*\]" /tmp/single_test_$$.tmp; then
                echo "[FAILED] $test_case (${test_duration_ms}ms)" | tee -a "$TEST_LOG" "$FAILURES_LOG"
                failed_tests=$((failed_tests + 1))
            else
                echo "[PASSED] $test_case (${test_duration_ms}ms)" | tee -a "$TEST_LOG"
                passed_tests=$((passed_tests + 1))
            fi
            
            # 显示测试输出
            cat /tmp/single_test_$$.tmp | tee -a "$TEST_LOG"
            
        else
            # 超时或其他错误
            local exit_code=$?
            if [ $exit_code -eq 124 ]; then
                echo "[TIMEOUT] $test_case (>3000ms)" | tee -a "$TEST_LOG" "$FAILURES_LOG"
                echo "TIMEOUT_DETECTED: 测试用例 '$test_case' 执行超过3秒被强制终止" | tee -a "$FAILURES_LOG"
                timeout_tests=$((timeout_tests + 1))
            else
                echo "[ERROR] $test_case (exit code: $exit_code)" | tee -a "$TEST_LOG" "$FAILURES_LOG"
                failed_tests=$((failed_tests + 1))
            fi
        fi
        
        # 清理临时文件
        rm -f /tmp/single_test_$$.tmp
        
        # 显示进度
        local progress=$((current_test_num * 100 / total_tests))
        echo "进度: ${current_test_num}/${total_tests} (${progress}%) - 通过:${passed_tests} 失败:${failed_tests} 超时:${timeout_tests}" | tee -a "$TEST_LOG"
    done
    
    # 记录最终统计
    {
        echo ""
        echo "=========================================="
        echo "测试执行完成统计"
        echo "=========================================="
        echo "总测试数: $total_tests"
        echo "通过测试: $passed_tests"
        echo "失败测试: $failed_tests"
        echo "超时测试: $timeout_tests"
        echo "完成时间: $(date)"
        echo "=========================================="
    } | tee -a "$TEST_LOG" "$RESULTS_LOG"
    
    # 设置退出代码
    if [ $failed_tests -gt 0 ] || [ $timeout_tests -gt 0 ]; then
        TEST_EXIT_CODE=1
    else
        TEST_EXIT_CODE=0
    fi
    
    # 创建兼容的输出文件
    cp "$TEST_LOG" /tmp/test_run_output_$$.tmp
    
    # 清理
    rm -f "$test_list_file"
}

# ========================================
# 测试执行阶段
# ========================================

run_test_suites() {
    log_header "测试执行阶段"
    
    # 检查测试可执行文件是否存在
    if [ ! -f "./wondertrader_tests" ]; then
        log_error "测试可执行文件不存在"
        exit 1
    fi

    log_info "开始执行测试套件..."
    log_info "每个测试用例超时限制: 3秒"
    TEST_START_TIME=$(date +%s)

    # 记录测试开始时间
    {
        echo "测试执行开始时间: $(date)"
        echo "测试命令: ./wondertrader_tests --gtest_timeout=3000"
        echo "单个测试用例超时: 3秒"
        echo "----------------------------------------"
    } >> "$TEST_LOG"

    # 执行测试并捕获输出，实现单个测试用例超时检测
    echo "" | tee -a "$TEST_LOG"  # 添加空行
    
    # 使用后台监控进程来检测超时的测试用例
    execute_tests_with_timeout
    echo "" | tee -a "$TEST_LOG"  # 添加空行

    TEST_END_TIME=$(date +%s)
    TEST_TIME=$((TEST_END_TIME - TEST_START_TIME))

    # 分析测试结果
    analyze_test_results /tmp/test_run_output_$$.tmp
    
    rm -f /tmp/test_run_output_$$.tmp

    if [ $TEST_EXIT_CODE -eq 0 ]; then
        log_success "测试套件执行完成"
        log_info "测试耗时: ${TEST_TIME} 秒"
    elif [ $TEST_EXIT_CODE -eq 124 ]; then
        log_warning "测试执行超时（600秒）"
        log_info "测试耗时: ${TEST_TIME} 秒"
    else
        log_warning "测试执行完成，但有失败用例"
        log_info "测试耗时: ${TEST_TIME} 秒"
    fi
}

# ========================================
# 测试结果分析
# ========================================

analyze_test_results() {
    local test_output_file="$1"
    
    log_header "测试结果分析"
    log_info "开始分析测试结果..."

    # 初始化计数器
    local total_tests=0
    local passed_tests=0
    local failed_tests=0
    local skipped_tests=0
    local disabled_tests=0
    local timeout_tests=0

    # 分析测试输出
    if [ -f "$test_output_file" ]; then
        # 从新的输出格式中提取统计信息
        if grep -q "测试执行完成统计" "$test_output_file"; then
            # 使用新格式的统计信息
            total_tests=$(grep "总测试数:" "$test_output_file" | tail -1 | grep -o '[0-9]*')
            passed_tests=$(grep "通过测试:" "$test_output_file" | tail -1 | grep -o '[0-9]*')
            failed_tests=$(grep "失败测试:" "$test_output_file" | tail -1 | grep -o '[0-9]*')
            timeout_tests=$(grep "超时测试:" "$test_output_file" | tail -1 | grep -o '[0-9]*')
        else
            # 回退到旧的解析方法
            local test_summary=$(grep -E "\[.*\].*tests.*from.*test.*case" "$test_output_file" | tail -1)
            local failure_summary=$(grep -E "FAILED.*test" "$test_output_file")
            local pass_summary=$(grep -E "PASSED.*test" "$test_output_file")

            # 从GTest输出解析统计信息
            if grep -q "Global test environment tear-down" "$test_output_file"; then
                # 从最后的汇总信息中提取数据
                local results_line=$(grep -E "\[.*\].*tests from.*test suite" "$test_output_file" | tail -1)
                if [ -n "$results_line" ]; then
                    total_tests=$(echo "$results_line" | sed -n 's/.*\[\s*\([0-9]*\)\s*\] tests.*/\1/p')
                fi
                
                # 查找失败的测试
                local failed_line=$(grep "FAILED  " "$test_output_file" | tail -1)
                if [ -n "$failed_line" ]; then
                    failed_tests=$(echo "$failed_line" | sed -n 's/.*(\s*\([0-9]*\)\s*ms total).*/\1/p')
                    failed_tests=$(grep -c "FAIL " "$test_output_file" 2>/dev/null || echo 0)
                fi
                
                # 统计超时测试用例（超过3秒的测试）
                timeout_tests=$(grep -c "TIMEOUT_DETECTED:" "$test_output_file" 2>/dev/null || echo 0)
                
                # 计算通过的测试（排除失败和超时）
                passed_tests=$((total_tests - failed_tests - timeout_tests))
            fi
        fi

        # 提取失败的测试用例详情
        {
            echo "========================================"
            echo "失败测试用例详细信息"
            echo "========================================"
            echo "分析时间: $(date)"
            echo "----------------------------------------"
        } >> "$FAILURES_LOG"

        # 查找失败的测试用例
        grep -A 5 -B 1 "FAIL " "$test_output_file" >> "$FAILURES_LOG" 2>/dev/null || echo "无失败测试用例详情" >> "$FAILURES_LOG"

        # 查找错误信息和异常
        {
            echo "----------------------------------------"
            echo "错误信息和异常汇总"
            echo "----------------------------------------"
        } >> "$FAILURES_LOG"

        # 提取各种错误模式
        grep -E "(error|Error|ERROR|exception|Exception|EXCEPTION|assertion|Assertion|ASSERTION)" "$test_output_file" | head -20 >> "$FAILURES_LOG" 2>/dev/null || echo "无明显错误信息" >> "$FAILURES_LOG"

        # 查找超时和崩溃
        {
            echo "----------------------------------------"
            echo "超时和崩溃信息"
            echo "----------------------------------------"
        } >> "$FAILURES_LOG"

        # 专门检测超过3秒的测试用例
        local timeout_tests=$(grep -c "TIMEOUT_DETECTED:" "$test_output_file" 2>/dev/null || echo 0)
        if [ $timeout_tests -gt 0 ]; then
            echo "检测到 $timeout_tests 个超过3秒的测试用例:" >> "$FAILURES_LOG"
            grep "TIMEOUT_DETECTED:" "$test_output_file" >> "$FAILURES_LOG" 2>/dev/null
        fi

        # 查找其他超时和崩溃信息
        grep -E "(timeout|Timeout|TIMEOUT|segmentation|segfault|crash|abort)" "$test_output_file" >> "$FAILURES_LOG" 2>/dev/null || echo "无其他超时或崩溃信息" >> "$FAILURES_LOG"

    else
        log_warning "无法找到测试输出文件进行分析"
        total_tests=0
        passed_tests=0
        failed_tests=0
    fi

    # 记录分析结果
    {
        echo "========================================"
        echo "测试结果统计"
        echo "========================================"
        echo "分析时间: $(date)"
        echo "总测试数: $total_tests"
        echo "通过测试: $passed_tests"
        echo "失败测试: $failed_tests"
        echo "超时测试: $timeout_tests"
        echo "跳过测试: $skipped_tests"
        echo "禁用测试: $disabled_tests"
        if [ $total_tests -gt 0 ]; then
            local success_rate=$(( (passed_tests * 100) / total_tests ))
            echo "成功率: ${success_rate}%"
        fi
        echo "========================================"
    } >> "$RESULTS_LOG"

    log_info "测试结果分析完成"
    log_info "总测试数: $total_tests, 通过: $passed_tests, 失败: $failed_tests, 超时: $timeout_tests"
}

# ========================================
# 生成测试摘要
# ========================================

generate_test_summary() {
    log_header "生成测试摘要"
    
    # 计算总测试时间
    END_TIME=$(date +%s)
    TOTAL_TEST_TIME=$((END_TIME - START_TIME))

    # 统计日志文件
    local warning_count=$(wc -l < "$FAILURES_LOG" 2>/dev/null || echo 0)
    local results_count=$(grep -c "总测试数" "$RESULTS_LOG" 2>/dev/null || echo 0)

    # 生成详细摘要
    {
        echo "========================================"
        echo "WonderTrader 测试执行摘要报告"
        echo "========================================"
        echo "测试时间戳: $TEST_TIMESTAMP"
        echo "总执行时间: ${TOTAL_TEST_TIME} 秒"
        echo "编译时间: ${COMPILE_TIME:-0} 秒"
        echo "测试时间: ${TEST_TIME:-0} 秒"
        echo "并行线程数: $COMPILE_JOBS"
        echo "----------------------------------------"
        echo "日志文件:"
        echo "- 完整测试日志: $TEST_LOG"
        echo "- 测试结果: $RESULTS_LOG"
        echo "- 失败分析: $FAILURES_LOG"
        echo "- 测试摘要: $SUMMARY_LOG"
        echo "----------------------------------------"
        echo "执行统计:"
        echo "- 问题记录数: $warning_count"
        echo "- 结果分析数: $results_count"
        echo "----------------------------------------"
        echo "文件大小:"
        echo "- 测试日志: $(du -h "$TEST_LOG" 2>/dev/null | cut -f1)B"
        echo "- 结果日志: $(du -h "$RESULTS_LOG" 2>/dev/null | cut -f1)B"
        echo "- 失败日志: $(du -h "$FAILURES_LOG" 2>/dev/null | cut -f1)B"
        echo "========================================"
        echo "测试完成时间: $(date)"
        echo "========================================"
    } | tee "$SUMMARY_LOG"

    # 在终端显示摘要
    echo "========================================"
    echo "测试执行摘要:"
    echo "- 总执行时间: ${TOTAL_TEST_TIME} 秒"
    echo "- 编译时间: ${COMPILE_TIME:-0} 秒"
    echo "- 测试时间: ${TEST_TIME:-0} 秒"
    echo "- 并行线程数: $COMPILE_JOBS"
    echo "- 问题记录数: $warning_count"
    echo "========================================"

    # 创建最新测试日志的软链接
    ln -sf "$(basename "$TEST_LOG")" "$LATEST_LOG"

    log_success "测试摘要生成完成"
    log_info "详细测试日志已保存到: $TEST_LOG"

    if [ $warning_count -gt 0 ]; then
        log_warning "发现 $warning_count 行问题记录，详情请查看: $FAILURES_LOG"
    fi

    echo "📋 查看测试摘要: cat $SUMMARY_LOG"
    echo "📋 查看最新日志: cat $LATEST_LOG"
    echo "📋 查看测试结果: cat $RESULTS_LOG"
    echo "📋 查看失败分析: cat $FAILURES_LOG"
}

# ========================================
# 主执行流程
# ========================================

main() {
    log_info "开始执行测试流程..."
    
    # 检查依赖
    check_dependencies
    
    # 设置构建环境
    setup_build_directory
    configure_tests
    build_tests
    
    # 执行测试
    run_test_suites
    
    # 生成报告
    generate_test_summary
    
    log_success "测试执行流程完成"
}

# ========================================
# 命令行参数处理
# ========================================

case "${1:-}" in
    "clean")
        log_info "仅清理构建目录"
        setup_build_directory
        ;;
    "build")
        log_info "仅构建测试"
        check_dependencies
        setup_build_directory
        configure_tests
        build_tests
        ;;
    "test")
        log_info "仅运行测试 (假设已构建)"
        if [ ! -d "$BUILD_DIR" ]; then
            log_error "构建目录不存在，请先运行构建"
            exit 1
        fi
        cd "$BUILD_DIR"
        run_test_suites
        generate_test_summary
        ;;
    "analyze")
        log_info "仅分析现有测试结果"
        if [ -f "$LATEST_LOG" ]; then
            analyze_test_results "$LATEST_LOG"
        else
            log_error "没有找到现有的测试日志"
            exit 1
        fi
        ;;
    *)
        main
        ;;
esac